home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / p_weapon.c1 < prev    next >
Encoding:
Text File  |  2002-11-29  |  37.1 KB  |  1,508 lines

  1. // g_weapon.c
  2.  
  3. #include "g_local.h"
  4. #include "m_player.h"
  5.  
  6.  
  7. static qboolean    is_quad;
  8. static byte        is_silenced;
  9.  
  10.  
  11. void weapon_grenade_fire (edict_t *ent, qboolean held);
  12.  
  13.  
  14. static void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
  15. {
  16.     vec3_t    _distance;
  17.  
  18.     VectorCopy (distance, _distance);
  19.     if (client->pers.hand == LEFT_HANDED)
  20.         _distance[1] *= -1;
  21.     else if (client->pers.hand == CENTER_HANDED)
  22.         _distance[1] = 0;
  23.     G_ProjectSource (point, _distance, forward, right, result);
  24. }
  25.  
  26.  
  27. /*
  28. ===============
  29. PlayerNoise
  30.  
  31. Each player can have two noise objects associated with it:
  32. a personal noise (jumping, pain, weapon firing), and a weapon
  33. target noise (bullet wall impacts)
  34.  
  35. Monsters that don't directly see the player can move
  36. to a noise in hopes of seeing the player from there.
  37. ===============
  38. */
  39. void PlayerNoise(edict_t *who, vec3_t where, int type)
  40. {
  41.     edict_t        *noise;
  42.  
  43.     if (type == PNOISE_WEAPON)
  44.     {
  45.         if (who->client->silencer_shots)
  46.         {
  47.             who->client->silencer_shots--;
  48.             return;
  49.         }
  50.     }
  51.  
  52.     if (deathmatch->value)
  53.         return;
  54.  
  55.     if (who->flags & FL_NOTARGET)
  56.         return;
  57.  
  58.  
  59.     if (!who->mynoise)
  60.     {
  61.         noise = G_Spawn();
  62.         noise->classname = "player_noise";
  63.         VectorSet (noise->mins, -8, -8, -8);
  64.         VectorSet (noise->maxs, 8, 8, 8);
  65.         noise->owner = who;
  66.         noise->svflags = SVF_NOCLIENT;
  67.         who->mynoise = noise;
  68.  
  69.         noise = G_Spawn();
  70.         noise->classname = "player_noise";
  71.         VectorSet (noise->mins, -8, -8, -8);
  72.         VectorSet (noise->maxs, 8, 8, 8);
  73.         noise->owner = who;
  74.         noise->svflags = SVF_NOCLIENT;
  75.         who->mynoise2 = noise;
  76.     }
  77.  
  78.     if (type == PNOISE_SELF || type == PNOISE_WEAPON)
  79.     {
  80.         noise = who->mynoise;
  81.         level.sound_entity = noise;
  82.         level.sound_entity_framenum = level.framenum;
  83.     }
  84.     else // type == PNOISE_IMPACT
  85.     {
  86.         noise = who->mynoise2;
  87.         level.sound2_entity = noise;
  88.         level.sound2_entity_framenum = level.framenum;
  89.     }
  90.  
  91.     VectorCopy (where, noise->s.origin);
  92.     VectorSubtract (where, noise->maxs, noise->absmin);
  93.     VectorAdd (where, noise->maxs, noise->absmax);
  94.     noise->teleport_time = level.time;
  95.     gi.linkentity (noise);
  96. }
  97.  
  98.  
  99. qboolean Pickup_Weapon (edict_t *ent, edict_t *other)
  100. {
  101.     int            index;
  102.     gitem_t        *ammo;
  103.  
  104.     index = ITEM_INDEX(ent->item);
  105.  
  106.     if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value) 
  107.         && other->client->pers.inventory[index])
  108.     {
  109.         if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) )
  110.             return false;    // leave the weapon for others to pickup
  111.     }
  112.  
  113.     other->client->pers.inventory[index]++;
  114.  
  115.     if (!(ent->spawnflags & DROPPED_ITEM) )
  116.     {
  117.         // give them some ammo with it
  118.         ammo = FindItem (ent->item->ammo);
  119.         if ( (int)dmflags->value & DF_INFINITE_AMMO )
  120.             Add_Ammo (other, ammo, 1000);
  121.         else
  122.             Add_Ammo (other, ammo, ammo->quantity);
  123.  
  124.         if (! (ent->spawnflags & DROPPED_PLAYER_ITEM) )
  125.         {
  126.             if (deathmatch->value)
  127.             {
  128.                 if ((int)(dmflags->value) & DF_WEAPONS_STAY)
  129.                     ent->flags |= FL_RESPAWN;
  130.                 else
  131.                     SetRespawn (ent, 30);
  132.             }
  133.             if (coop->value)
  134.                 ent->flags |= FL_RESPAWN;
  135.         }
  136.     }
  137.  
  138.     if (other->client->pers.weapon != ent->item && 
  139.         (other->client->pers.inventory[index] == 1) &&
  140.         ( !deathmatch->value || other->client->pers.weapon == FindItem("blaster") ) )
  141.         other->client->newweapon = ent->item;
  142.  
  143.     return true;
  144. }
  145.  
  146.  
  147. /*
  148. ===============
  149. ChangeWeapon
  150.  
  151. The old weapon has been dropped all the way, so make the new one
  152. current
  153. ===============
  154. */
  155. void ChangeWeapon (edict_t *ent)
  156. {
  157.     if (ent->client->grenade_time)
  158.     {
  159.         ent->client->grenade_time = level.time;
  160.         ent->client->weapon_sound = 0;
  161.         weapon_grenade_fire (ent, false);
  162.         ent->client->grenade_time = 0;
  163.     }
  164.  
  165.     ent->client->pers.lastweapon = ent->client->pers.weapon;
  166.     ent->client->pers.weapon = ent->client->newweapon;
  167.     ent->client->newweapon = NULL;
  168.     ent->client->machinegun_shots = 0;
  169.  
  170.     if (ent->client->pers.weapon && ent->client->pers.weapon->ammo)
  171.         ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo));
  172.     else
  173.         ent->client->ammo_index = 0;
  174.  
  175.     if (!ent->client->pers.weapon)
  176.     {    // dead
  177.         ent->client->ps.gunindex = 0;
  178.         return;
  179.     }
  180.  
  181.     ent->client->weaponstate = WEAPON_ACTIVATING;
  182.     ent->client->ps.gunframe = 0;
  183.     ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
  184. }
  185.  
  186. /*
  187. =================
  188. NoAmmoWeaponChange
  189. =================
  190. */
  191. void NoAmmoWeaponChange (edict_t *ent)
  192. {
  193.     if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))]
  194.         &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("Disruptor"))] )
  195.     {
  196.         ent->client->newweapon = FindItem ("Disruptor");
  197.         return;
  198.     }
  199.     if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("alien smart grenade"))]
  200.         &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("Alien Smartgun"))] )
  201.     {
  202.         ent->client->newweapon = FindItem ("Alien Smartgun");
  203.         return;
  204.     }
  205.     if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("rockets"))]
  206.         &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("Rocket Launcher"))] )
  207.     {
  208.         ent->client->newweapon = FindItem ("Rocket Launcher");
  209.         return;
  210.     }
  211.     if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("rockets"))]
  212.         &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("Homing Rocket Launcher"))] )
  213.     {
  214.         ent->client->newweapon = FindItem ("Homing Rocket Launcher");
  215.         return;
  216.     }
  217.     if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("napalm"))]
  218.         &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("Flame Thrower"))] )
  219.     {
  220.         ent->client->newweapon = FindItem ("Flame Thrower");
  221.         return;
  222.     }
  223.     
  224.     if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] > 1
  225.         &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("Pulse Rifle"))] )
  226.     {
  227.         ent->client->newweapon = FindItem ("Pulse Rifle");
  228.         return;
  229.     }
  230.     if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))]
  231.         &&  ent->client->pers.inventory[ITEM_INDEX(FindItem("Alien Disruptor"))] )
  232.     {
  233.         ent->client->newweapon = FindItem ("Alien Disruptor");
  234.         return;
  235.     }
  236.     ent->client->newweapon = FindItem ("blaster");
  237. }
  238.  
  239. /*
  240. =================
  241. Think_Weapon
  242.  
  243. Called by ClientBeginServerFrame and ClientThink
  244. =================
  245. */
  246. void Think_Weapon (edict_t *ent)
  247. {
  248.     // if just died, put the weapon away
  249.     if (ent->health < 1)
  250.     {
  251.         ent->client->newweapon = NULL;
  252.         ChangeWeapon (ent);
  253.     }
  254.  
  255.     // call active weapon think routine
  256.     if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink)
  257.     {
  258.         is_quad = (ent->client->quad_framenum > level.framenum);
  259.         if (ent->client->silencer_shots)
  260.             is_silenced = MZ_SILENCED;
  261.         else
  262.             is_silenced = 0;
  263.         ent->client->pers.weapon->weaponthink (ent);
  264.     }
  265. }
  266.  
  267.  
  268. /*
  269. ================
  270. Use_Weapon
  271.  
  272. Make the weapon ready if there is ammo
  273. ================
  274. */
  275. void Use_Weapon (edict_t *ent, gitem_t *item)
  276. {
  277.     int            ammo_index;
  278.     gitem_t        *ammo_item;
  279.  
  280.     // see if we're already using it
  281.     if (item == ent->client->pers.weapon)
  282.         return;
  283.  
  284.     if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO))
  285.     {
  286.         ammo_item = FindItem(item->ammo);
  287.         ammo_index = ITEM_INDEX(ammo_item);
  288.  
  289.         if (!ent->client->pers.inventory[ammo_index])
  290.         {
  291.             gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
  292.             return;
  293.         }
  294.  
  295.         if (ent->client->pers.inventory[ammo_index] < item->quantity)
  296.         {
  297.             gi.cprintf (ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
  298.             return;
  299.         }
  300.     }
  301.  
  302.     // change to this weapon when down
  303.     ent->client->newweapon = item;
  304. }
  305.  
  306.  
  307.  
  308. /*
  309. ================
  310. Drop_Weapon
  311. ================
  312. */
  313. void Drop_Weapon (edict_t *ent, gitem_t *item)
  314. {
  315.     int        index;
  316.  
  317.     if ((int)(dmflags->value) & DF_WEAPONS_STAY)
  318.         return;
  319.  
  320.     index = ITEM_INDEX(item);
  321.     // see if we're already using it
  322.     if ( ((item == ent->client->pers.weapon) || (item == ent->client->newweapon))&& (ent->client->pers.inventory[index] == 1) )
  323.     {
  324.         gi.cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n");
  325.         return;
  326.     }
  327.  
  328.     Drop_Item (ent, item);
  329.     ent->client->pers.inventory[index]--;
  330. }
  331.  
  332.  
  333. /*
  334. ================
  335. Weapon_Generic
  336.  
  337. A generic function to handle the basics of weapon thinking
  338. ================
  339. */
  340. #define FRAME_FIRE_FIRST        (FRAME_ACTIVATE_LAST + 1)
  341. #define FRAME_IDLE_FIRST        (FRAME_FIRE_LAST + 1)
  342. #define FRAME_DEACTIVATE_FIRST    (FRAME_IDLE_LAST + 1)
  343.  
  344. void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent))
  345. {
  346.     int        n;
  347.  
  348.     if (ent->client->weaponstate == WEAPON_DROPPING)
  349.     {
  350.         if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST)
  351.         {
  352.             ChangeWeapon (ent);
  353.             return;
  354.         }
  355.  
  356.         ent->client->ps.gunframe++;
  357.         return;
  358.     }
  359.  
  360.     if (ent->client->weaponstate == WEAPON_ACTIVATING)
  361.     {
  362.         if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST)
  363.         {
  364.             ent->client->weaponstate = WEAPON_READY;
  365.             ent->client->ps.gunframe = FRAME_IDLE_FIRST;
  366.             return;
  367.         }
  368.  
  369.         ent->client->ps.gunframe++;
  370.         return;
  371.     }
  372.  
  373.     if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING))
  374.     {
  375.         ent->client->weaponstate = WEAPON_DROPPING;
  376.         ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST;
  377.         return;
  378.     }
  379.  
  380.     if (ent->client->weaponstate == WEAPON_READY)
  381.     {
  382.         if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
  383.         {
  384.             ent->client->latched_buttons &= ~BUTTON_ATTACK;
  385.             if ((!ent->client->ammo_index) || 
  386.                 ( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity))
  387.             {
  388.                 ent->client->ps.gunframe = FRAME_FIRE_FIRST;
  389.                 ent->client->weaponstate = WEAPON_FIRING;
  390.  
  391.                 // start the animation
  392.                 ent->client->anim_priority = ANIM_ATTACK;
  393.                 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
  394.                 {
  395.                     ent->s.frame = FRAME_crattak1-1;
  396.                     ent->client->anim_end = FRAME_crattak9;
  397.                 }
  398.                 else
  399.                 {
  400.                     ent->s.frame = FRAME_attack1-1;
  401.                     ent->client->anim_end = FRAME_attack8;
  402.                 }
  403.             }
  404.             else
  405.             {
  406.                 if (level.time >= ent->pain_debounce_time)
  407.                 {
  408.                     gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
  409.                     ent->pain_debounce_time = level.time + 1;
  410.                 }
  411.                 NoAmmoWeaponChange (ent);
  412.             }
  413.         }
  414.         else
  415.         {
  416.             if (ent->client->ps.gunframe == FRAME_IDLE_LAST)
  417.             {
  418.                 ent->client->ps.gunframe = FRAME_IDLE_FIRST;
  419.                 return;
  420.             }
  421.  
  422.             if (pause_frames)
  423.             {
  424.                 for (n = 0; pause_frames[n]; n++)
  425.                 {
  426.                     if (ent->client->ps.gunframe == pause_frames[n])
  427.                     {
  428.                         if (rand()&15)
  429.                             return;
  430.                     }
  431.                 }
  432.             }
  433.  
  434.             ent->client->ps.gunframe++;
  435.             return;
  436.         }
  437.     }
  438.  
  439.     if (ent->client->weaponstate == WEAPON_FIRING)
  440.     {
  441.         for (n = 0; fire_frames[n]; n++)
  442.         {
  443.             if (ent->client->ps.gunframe == fire_frames[n])
  444.             {
  445.                 if (ent->client->quad_framenum > level.framenum)
  446.                     gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0);
  447.  
  448.                 fire (ent);
  449.                 break;
  450.             }
  451.         }
  452.  
  453.         if (!fire_frames[n])
  454.             ent->client->ps.gunframe++;
  455.  
  456.         if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1)
  457.             ent->client->weaponstate = WEAPON_READY;
  458.     }
  459. }
  460.  
  461. //plasma fire routines
  462. void weapon_plasma_fire (edict_t *ent)
  463. {
  464.     vec3_t        start;
  465.     vec3_t        forward, right;
  466.     vec3_t        offset;
  467.     int            damage;
  468.     int            kick;
  469.  
  470.     if (deathmatch->value)
  471.     {    // normal damage is too extreme in dm
  472.         damage = 100;
  473.         kick = 200;
  474.     }
  475.     else
  476.     {
  477.         damage = 50;
  478.         kick = 5;
  479.     }
  480.  
  481.     if (is_quad)
  482.     {
  483.         damage *= 4;
  484.         kick *= 4;
  485.     }
  486.  
  487.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  488.  
  489.     VectorScale (forward, -3, ent->client->kick_origin);
  490.     ent->client->kick_angles[0] = -3;
  491.  
  492.     VectorSet(offset, 32, 5,  ent->viewheight-5);
  493.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  494.     fire_plasma (ent, start, forward, damage, kick);
  495.  
  496.     // send muzzle flash
  497.     gi.WriteByte (svc_muzzleflash);
  498.     gi.WriteShort (ent-g_edicts);
  499.     gi.WriteByte (MZ_RAILGUN | is_silenced);
  500.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  501.  
  502.     ent->client->ps.gunframe++;
  503.     PlayerNoise(ent, start, PNOISE_WEAPON);
  504.  
  505.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  506.         ent->client->pers.inventory[ent->client->ammo_index]= ent->client->pers.inventory[ent->client->ammo_index]-2;
  507. }
  508.  
  509. /*
  510. ======================================================================
  511.  
  512. GRENADE
  513.  
  514. ======================================================================
  515. */
  516.  
  517. #define GRENADE_TIMER        3.0
  518. #define GRENADE_MINSPEED    400
  519. #define GRENADE_MAXSPEED    800
  520.  
  521. void weapon_grenade_fire (edict_t *ent, qboolean held)
  522. {
  523.     vec3_t    offset;
  524.     vec3_t    forward, right;
  525.     vec3_t    start;
  526.     int        damage = 125;
  527.     float    timer;
  528.     int        speed;
  529.     float    radius;
  530.  
  531.     radius = damage+40;
  532.     if (is_quad)
  533.         damage *= 4;
  534.  
  535.     VectorSet(offset, 8, 8, ent->viewheight-8);
  536.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  537.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  538.  
  539.     timer = ent->client->grenade_time - level.time;
  540.     speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER);
  541.     fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
  542.  
  543.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  544.         ent->client->pers.inventory[ent->client->ammo_index]--;
  545.  
  546.     ent->client->grenade_time = level.time + 1.0;
  547. }
  548.  
  549. void Weapon_Grenade (edict_t *ent)
  550. {
  551.     if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
  552.     {
  553.         ChangeWeapon (ent);
  554.         return;
  555.     }
  556.  
  557.     if (ent->client->weaponstate == WEAPON_ACTIVATING)
  558.     {
  559.         ent->client->weaponstate = WEAPON_READY;
  560.         ent->client->ps.gunframe = 16;
  561.         return;
  562.     }
  563.  
  564.     if (ent->client->weaponstate == WEAPON_READY)
  565.     {
  566.         if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
  567.         {
  568.             ent->client->latched_buttons &= ~BUTTON_ATTACK;
  569.             if (ent->client->pers.inventory[ent->client->ammo_index])
  570.             {
  571.                 ent->client->ps.gunframe = 1;
  572.                 ent->client->weaponstate = WEAPON_FIRING;
  573.                 ent->client->grenade_time = 0;
  574.             }
  575.             else
  576.             {
  577.                 if (level.time >= ent->pain_debounce_time)
  578.                 {
  579.                     gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
  580.                     ent->pain_debounce_time = level.time + 1;
  581.                 }
  582.                 NoAmmoWeaponChange (ent);
  583.             }
  584.             return;
  585.         }
  586.  
  587.         if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48))
  588.         {
  589.             if (rand()&15)
  590.                 return;
  591.         }
  592.  
  593.         if (++ent->client->ps.gunframe > 48)
  594.             ent->client->ps.gunframe = 16;
  595.         return;
  596.     }
  597.  
  598.     if (ent->client->weaponstate == WEAPON_FIRING)
  599.     {
  600.         if (ent->client->ps.gunframe == 5)
  601.             gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
  602.  
  603.         if (ent->client->ps.gunframe == 11)
  604.         {
  605.             if (!ent->client->grenade_time)
  606.             {
  607.                 ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
  608.                 ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav");
  609.             }
  610.  
  611.             // they waited too long, detonate it in their hand
  612.             if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
  613.             {
  614.                 ent->client->weapon_sound = 0;
  615.                 weapon_grenade_fire (ent, true);
  616.                 ent->client->grenade_blew_up = true;
  617.             }
  618.  
  619.             if (ent->client->buttons & BUTTON_ATTACK)
  620.                 return;
  621.  
  622.             if (ent->client->grenade_blew_up)
  623.             {
  624.                 if (level.time >= ent->client->grenade_time)
  625.                 {
  626.                     ent->client->ps.gunframe = 15;
  627.                     ent->client->grenade_blew_up = false;
  628.                 }
  629.                 else
  630.                 {
  631.                     return;
  632.                 }
  633.             }
  634.         }
  635.  
  636.         if (ent->client->ps.gunframe == 12)
  637.         {
  638.             ent->client->weapon_sound = 0;
  639.             weapon_grenade_fire (ent, false);
  640.         }
  641.  
  642.         if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time))
  643.             return;
  644.  
  645.         ent->client->ps.gunframe++;
  646.  
  647.         if (ent->client->ps.gunframe == 16)
  648.         {
  649.             ent->client->grenade_time = 0;
  650.             ent->client->weaponstate = WEAPON_READY;
  651.         }
  652.     }
  653. }
  654.  
  655. /*
  656. ======================================================================
  657.  
  658. GRENADE LAUNCHER
  659.  
  660. ======================================================================
  661. */
  662.  
  663. void weapon_grenadelauncher_fire (edict_t *ent)
  664. {
  665.     vec3_t    offset;
  666.     vec3_t    forward, right;
  667.     vec3_t    start;
  668.     int        damage = 120;
  669.     float    radius;
  670.  
  671.     radius = damage+40;
  672.     if (is_quad)
  673.         damage *= 4;
  674.  
  675.     VectorSet(offset, 8, 8, ent->viewheight-8);
  676.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  677.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  678.  
  679.     VectorScale (forward, -2, ent->client->kick_origin);
  680.     ent->client->kick_angles[0] = -1;
  681.     start[2] = start[2] + 4;
  682.     forward[0] = forward[0] * 1.5;
  683.     forward[1] = forward[1] * 1.5;
  684.     forward[2] = forward[2] * 1.5;
  685.     fire_grenade (ent, start, forward, damage, 600, 12.5, radius);
  686.  
  687.     gi.WriteByte (svc_muzzleflash);
  688.     gi.WriteShort (ent-g_edicts);
  689.     gi.WriteByte (MZ_GRENADE | is_silenced);
  690.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  691.  
  692.     ent->client->ps.gunframe++;
  693.  
  694.     PlayerNoise(ent, start, PNOISE_WEAPON);
  695.  
  696.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  697.         ent->client->pers.inventory[ent->client->ammo_index]--;
  698. }
  699.  
  700. void Weapon_Chaingun (edict_t *ent)
  701. {
  702.     static int    pause_frames[]    = {34, 51, 59, 0};
  703.     static int    fire_frames[]    = {6, 7, 8, 9, 10, 9, 0};
  704.  
  705.     Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
  706. }
  707.  
  708. /*
  709. ======================================================================
  710.  
  711. ROCKET
  712.  
  713. ======================================================================
  714. */
  715.  
  716. void Weapon_RocketLauncher_Fire (edict_t *ent)
  717. {
  718.     vec3_t    offset, start;
  719.     vec3_t    forward, right;
  720.     int        damage;
  721.     float    damage_radius;
  722.     int        radius_damage;
  723.  
  724.     damage = 200 + (int)(random() * 20.0);
  725.     radius_damage = 120;
  726.     damage_radius = 120;
  727.     if (is_quad)
  728.     {
  729.         damage *= 4;
  730.         radius_damage *= 4;
  731.     }
  732.  
  733.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  734.  
  735.     VectorScale (forward, -2, ent->client->kick_origin);
  736.     ent->client->kick_angles[0] = -1;
  737.  
  738.     VectorSet(offset, 8, 8, ent->viewheight-4);
  739.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  740.     fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage);
  741.  
  742.     // send muzzle flash
  743.     gi.WriteByte (svc_muzzleflash);
  744.     gi.WriteShort (ent-g_edicts);
  745.     gi.WriteByte (MZ_ROCKET | is_silenced);
  746.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  747.  
  748.     ent->client->ps.gunframe++;
  749.  
  750.     PlayerNoise(ent, start, PNOISE_WEAPON);
  751.  
  752.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  753.         ent->client->pers.inventory[ent->client->ammo_index]--;
  754. }
  755.  
  756. void Weapon_RocketLauncher (edict_t *ent)
  757. {
  758.     static int    pause_frames[]    = {25, 33, 42, 50, 0};
  759.     static int    fire_frames[]    = {5, 0};
  760.  
  761.     Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire);
  762. }
  763.  
  764. void weapon_stinger_fire (edict_t *ent)
  765. {
  766.     vec3_t    offset, start;
  767.     vec3_t    forward, right;
  768.     int        damage;
  769.     float    damage_radius;
  770.     int        radius_damage;
  771.  
  772.     damage = 200 + (int)(random() * 20.0);
  773.     radius_damage = 220;
  774.     damage_radius = 120;
  775.     if (is_quad)
  776.     {
  777.         damage *= 4;
  778.         radius_damage *= 4;
  779.     }
  780.  
  781.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  782.  
  783.     VectorScale (forward, -2, ent->client->kick_origin);
  784.     ent->client->kick_angles[0] = -1;
  785.  
  786.     VectorSet(offset, 16, 16, ent->viewheight-0);
  787.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  788.     fire_stinger (ent, start, forward, damage, 650, damage_radius, radius_damage);
  789.  
  790.     // send muzzle flash
  791.     gi.WriteByte (svc_muzzleflash);
  792.     gi.WriteShort (ent-g_edicts);
  793.     gi.WriteByte (MZ_ROCKET | is_silenced);
  794.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  795.  
  796.     ent->client->ps.gunframe++;
  797.  
  798.     PlayerNoise(ent, start, PNOISE_WEAPON);
  799.  
  800.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  801.         ent->client->pers.inventory[ent->client->ammo_index]--;
  802. }
  803. void weapon_sidewinder_fire (edict_t *ent)
  804. {
  805.     vec3_t    offset, start;
  806.     vec3_t    forward, right;
  807.     int        damage;
  808.     float    damage_radius;
  809.     int        radius_damage;
  810.  
  811.     damage = 100 + (int)(random() * 20.0);
  812.     radius_damage = 80;
  813.     damage_radius = 100;
  814.     if (is_quad)
  815.     {
  816.         damage *= 4;
  817.         radius_damage *= 4;
  818.     }
  819.  
  820.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  821.  
  822.     VectorScale (forward, -2, ent->client->kick_origin);
  823.     ent->client->kick_angles[0] = -1;
  824.  
  825.     VectorSet(offset, 8, 8, ent->viewheight-4);
  826.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  827.     fire_sidewinder (ent, start, forward, damage, 250, damage_radius, radius_damage);
  828.  
  829.     // send muzzle flash
  830.     gi.WriteByte (svc_muzzleflash);
  831.     gi.WriteShort (ent-g_edicts);
  832.     gi.WriteByte (MZ_ROCKET | is_silenced);
  833.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  834.  
  835.     ent->client->ps.gunframe++;
  836.  
  837.     PlayerNoise(ent, start, PNOISE_WEAPON);
  838.  
  839.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  840.         ent->client->pers.inventory[ent->client->ammo_index]--;
  841. }
  842. /*
  843. ======================================================================
  844.  
  845. BLASTER / HYPERBLASTER
  846.  
  847. ======================================================================
  848. */
  849.  
  850. void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect)
  851. {
  852.     vec3_t    forward, right;
  853.     vec3_t    start;
  854.     vec3_t    offset;
  855.  
  856.     if (is_quad)
  857.         damage *= 4;
  858.  
  859.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  860.  
  861.     VectorScale (forward, -3, ent->client->kick_origin);
  862.     ent->client->kick_angles[0] = -3;
  863.  
  864.     if(hyper)
  865.         VectorSet(offset, 32, 6, ent->viewheight-5);
  866.     else
  867.         VectorSet(offset, 30, 6, ent->viewheight-5);
  868.     VectorAdd (offset, g_offset, offset);
  869.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  870.  
  871.     if(hyper)
  872.         fire_blaster (ent, start, forward, damage, 2800, effect, hyper);
  873.     else
  874.         fire_blaster_beam (ent, start, forward, damage, 0);
  875.  
  876.     // send muzzle flash
  877.     gi.WriteByte (svc_muzzleflash);
  878.     gi.WriteShort (ent-g_edicts);
  879.     if (hyper)
  880.         gi.WriteByte (MZ_HYPERBLASTER | is_silenced);
  881.     else
  882.         gi.WriteByte (MZ_BLASTER | is_silenced);
  883.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  884.     PlayerNoise(ent, start, PNOISE_WEAPON);
  885.     //create visual muzzle flash sprite!
  886.  
  887.     if(!hyper)
  888.     {
  889.         VectorAdd(start, forward, start);
  890.         gi.WriteByte (svc_temp_entity);
  891.         gi.WriteByte (TE_BLASTER_MUZZLEFLASH);
  892.         gi.WritePosition (start);
  893.         gi.multicast (start, MULTICAST_PVS);
  894.     }
  895. }
  896.  
  897.  
  898. void Weapon_Blaster_Fire (edict_t *ent)
  899. {
  900.     int        damage;
  901.  
  902.     if (deathmatch->value)
  903.         damage = 20;
  904.     else
  905.         damage = 15;
  906.     Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER);
  907.     ent->client->ps.gunframe++;
  908. }
  909.  
  910. void Weapon_Blaster (edict_t *ent)
  911. {
  912.     static int    pause_frames[]    = {19, 32, 0};
  913.     static int    fire_frames[]    = {5,7, 0};
  914.  
  915.     Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire);
  916. }
  917.  
  918.  
  919. void Weapon_HyperBlaster_Fire (edict_t *ent)
  920. {
  921.     //float    rotation; rem out unneed variable
  922.     vec3_t    offset;
  923.     int        effect;
  924.     int        damage;
  925.  
  926.     //rem out the sound, stays on constantly  fix it later
  927.     //ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav");
  928.  
  929.     if (!(ent->client->buttons & BUTTON_ATTACK))
  930.     {
  931.         ent->client->ps.gunframe++;
  932.     }
  933.     else
  934.     {
  935.         if (! ent->client->pers.inventory[ent->client->ammo_index] )
  936.         {
  937.             if (level.time >= ent->pain_debounce_time)
  938.             {
  939.                 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
  940.                 ent->pain_debounce_time = level.time + 1;
  941.             }
  942.             NoAmmoWeaponChange (ent);
  943.         }
  944.         else
  945.         {
  946.             //rem out the rotation thats annoying 
  947.             //rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6;
  948.             offset[0] = 0;
  949.             offset[1] = 0;
  950.             offset[2] = 1;
  951.  
  952.             if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9))
  953.                 effect = EF_HYPERBLASTER;
  954.             else
  955.                 effect = 0;
  956.             if (deathmatch->value)
  957.                 damage = 25;
  958.             else
  959.                 damage = 30;
  960.             Blaster_Fire (ent, offset, damage, true, effect);
  961.             if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  962.                 ent->client->pers.inventory[ent->client->ammo_index]--;
  963.         }
  964.  
  965.         ent->client->ps.gunframe++;
  966.         if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index])
  967.             ent->client->ps.gunframe = 6;
  968.     }
  969.  
  970.     if (ent->client->ps.gunframe == 12)
  971.     {
  972.         gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0);
  973.         ent->client->weapon_sound = 0;
  974.     }
  975.  
  976. }
  977.  
  978. void Weapon_Railgun (edict_t *ent)
  979. {
  980.     static int    pause_frames[]    = {0 };
  981.     static int    fire_frames[]    = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0};
  982.  
  983.     Weapon_Generic (ent, 5, 24, 53, 57, pause_frames, fire_frames, Weapon_HyperBlaster_Fire);
  984. }
  985.  
  986. /*
  987. ======================================================================
  988.  
  989. MACHINEGUN / CHAINGUN
  990.  
  991. ======================================================================
  992. */
  993.  
  994. void Machinegun_Fire (edict_t *ent)
  995. {
  996.     int            i;
  997.     int            shots;
  998.     vec3_t        start;
  999.     vec3_t        forward, right;
  1000.     vec3_t        offset;
  1001.     int            damage;
  1002.     int            kick = 2;
  1003.  
  1004.     if (deathmatch->value)
  1005.         damage = 6;
  1006.     else
  1007.         damage = 20;
  1008.  
  1009.     ent->client->ps.gunframe++;
  1010.     
  1011.     shots = 1;
  1012.  
  1013.     if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
  1014.         shots = ent->client->pers.inventory[ent->client->ammo_index];
  1015.  
  1016.     if (!shots)
  1017.     {
  1018.         if (level.time >= ent->pain_debounce_time)
  1019.         {
  1020.             gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
  1021.             ent->pain_debounce_time = level.time + 1;
  1022.         }
  1023.         NoAmmoWeaponChange (ent);
  1024.         return;
  1025.     }
  1026.  
  1027.     if (is_quad)
  1028.     {
  1029.         damage *= 4;
  1030.         kick *= 4;
  1031.     }
  1032.  
  1033.     for (i=0 ; i<3 ; i++)
  1034.     {
  1035.         ent->client->kick_origin[i] = crandom() * 0.35;
  1036.         ent->client->kick_angles[i] = crandom() * 0.7;
  1037.     }
  1038.  
  1039.     AngleVectors (ent->client->v_angle, forward, right, NULL);//was up
  1040.     VectorScale (forward, -3, ent->client->kick_origin);
  1041.     ent->client->kick_angles[0] = -3;
  1042.  
  1043.     for (i=0 ; i<shots ; i++)
  1044.     {
  1045.         VectorSet(offset, 32, 5, ent->viewheight-5);
  1046.         P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  1047.         fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN);
  1048.     }
  1049.  
  1050.     // send muzzle flash
  1051.     gi.WriteByte (svc_muzzleflash);
  1052.     gi.WriteShort (ent-g_edicts);
  1053.     gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced);
  1054.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  1055.  
  1056. //    PlayerNoise(ent, start, PNOISE_WEAPON);
  1057.  
  1058.     //create visual muzzle flash sprite!
  1059.     
  1060. //    forward[0] = forward[0] * 32;
  1061. //    forward[1] = forward[1] * 32;
  1062.  
  1063.     VectorAdd(start, forward, start);
  1064.     gi.WriteByte (svc_temp_entity);
  1065.     gi.WriteByte (TE_BLASTER_MUZZLEFLASH);
  1066.     gi.WritePosition (start);
  1067.     gi.multicast (start, MULTICAST_PVS);
  1068.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  1069.         ent->client->pers.inventory[ent->client->ammo_index] -= shots;
  1070.  
  1071. }
  1072.  
  1073. void Weapon_SuperShotgun (edict_t *ent)
  1074. {
  1075.     static int    pause_frames[]    = {0};//38, 43, 51, 61, 0};
  1076.     static int    fire_frames[]    = {5, 6, 7, 8, 9, 10, 11, 12, 13, 0};
  1077.  
  1078.     Weapon_Generic (ent, 4, 13, 43, 46, pause_frames, fire_frames, Machinegun_Fire);
  1079.  
  1080. }
  1081.  
  1082. void Chaingun_Fire (edict_t *ent)
  1083. {
  1084.     int            i;
  1085.     int            shots;
  1086.     vec3_t        start;
  1087.     vec3_t        forward, right, up;
  1088.     float        r, u;
  1089.     vec3_t        offset;
  1090.     int            damage;
  1091.     int            kick = 2;
  1092.  
  1093.     if (deathmatch->value)
  1094.         damage = 6;
  1095.     else
  1096.         damage = 8;
  1097.  
  1098.     if (ent->client->ps.gunframe == 5)
  1099.         gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0);
  1100.  
  1101.     if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK))
  1102.     {
  1103.         ent->client->ps.gunframe = 32;
  1104.         ent->client->weapon_sound = 0;
  1105.         return;
  1106.     }
  1107.     else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK)
  1108.         && ent->client->pers.inventory[ent->client->ammo_index])
  1109.     {
  1110.         ent->client->ps.gunframe = 15;
  1111.     }
  1112.     else
  1113.     {
  1114.         ent->client->ps.gunframe++;
  1115.     }
  1116.  
  1117.     if (ent->client->ps.gunframe == 22)
  1118.     {
  1119.         ent->client->weapon_sound = 0;
  1120.         gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0);
  1121.     }
  1122.     else
  1123.     {
  1124.         ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav");
  1125.     }
  1126.  
  1127.     if (ent->client->ps.gunframe <= 9)
  1128.         shots = 1;
  1129.     else if (ent->client->ps.gunframe <= 14)
  1130.     {
  1131.         if (ent->client->buttons & BUTTON_ATTACK)
  1132.             shots = 2;
  1133.         else
  1134.             shots = 1;
  1135.     }
  1136.     else
  1137.         shots = 3;
  1138.  
  1139.     if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
  1140.         shots = ent->client->pers.inventory[ent->client->ammo_index];
  1141.  
  1142.     if (!shots)
  1143.     {
  1144.         if (level.time >= ent->pain_debounce_time)
  1145.         {
  1146.             gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
  1147.             ent->pain_debounce_time = level.time + 1;
  1148.         }
  1149.         NoAmmoWeaponChange (ent);
  1150.         return;
  1151.     }
  1152.  
  1153.     if (is_quad)
  1154.     {
  1155.         damage *= 4;
  1156.         kick *= 4;
  1157.     }
  1158.  
  1159.     for (i=0 ; i<3 ; i++)
  1160.     {
  1161.         ent->client->kick_origin[i] = crandom() * 0.35;
  1162.         ent->client->kick_angles[i] = crandom() * 0.7;
  1163.     }
  1164.  
  1165.     AngleVectors (ent->client->v_angle, forward, right, up);
  1166.  
  1167.     for (i=0 ; i<shots ; i++)
  1168.     {
  1169.         // get start / end positions
  1170.         r = 7 + crandom()*4;
  1171.         u = crandom()*4;
  1172.         VectorSet(offset, 0, r, u + ent->viewheight-8);
  1173.         P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  1174.  
  1175.         fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN);
  1176.     }
  1177.  
  1178.     // send muzzle flash
  1179.     gi.WriteByte (svc_muzzleflash);
  1180.     gi.WriteShort (ent-g_edicts);
  1181.     gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced);
  1182.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  1183.  
  1184.     PlayerNoise(ent, start, PNOISE_WEAPON);
  1185.  
  1186.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  1187.         ent->client->pers.inventory[ent->client->ammo_index] -= shots;
  1188. }
  1189.  
  1190.  
  1191. void Weapon_Machinegun (edict_t *ent)
  1192. {
  1193.     static int    pause_frames[]    = {38, 43, 51, 61, 0};
  1194.     static int    fire_frames[]    = {5, 6, 0};
  1195.  
  1196.     Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Machinegun_Fire);
  1197. }
  1198.  
  1199. /*
  1200. ======================================================================
  1201.  
  1202. SHOTGUN / SUPERSHOTGUN
  1203.  
  1204. ======================================================================
  1205. */
  1206. void weapon_floater_fire (edict_t *ent)
  1207. {
  1208.     vec3_t    offset, start;
  1209.     vec3_t    forward, right;
  1210.     int        damage;
  1211.     float    damage_radius;
  1212.     int        radius_damage;
  1213.     
  1214.     damage = 100 + (int)(random() * 20.0);
  1215.     radius_damage = 120;
  1216.     damage_radius = 120;
  1217.     if (is_quad)
  1218.     {
  1219.         damage *= 4;
  1220.         radius_damage *= 4;
  1221.     }
  1222.  
  1223.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  1224.  
  1225.     VectorScale (forward, -2, ent->client->kick_origin);
  1226.     ent->client->kick_angles[0] = -1;
  1227.  
  1228.     VectorSet(offset, 8, 8, ent->viewheight-4);
  1229.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  1230.     forward[0] = forward[0] * 2.6;
  1231.     forward[1] = forward[1] * 2.6;
  1232.     fire_floater (ent, start, forward, damage, 100, damage_radius, radius_damage, 8); 
  1233.     // send muzzle flash
  1234.     gi.WriteByte (svc_muzzleflash);
  1235.     gi.WriteShort (ent-g_edicts);
  1236.     gi.WriteByte (MZ_SHOTGUN | is_silenced);
  1237.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  1238.  
  1239.     ent->client->ps.gunframe++;
  1240.  
  1241.     PlayerNoise(ent, start, PNOISE_WEAPON);
  1242.  
  1243. //create visual muzzle flash sprite!
  1244.     
  1245.     forward[0] = forward[0] * 10;
  1246.     forward[1] = forward[1] * 10;
  1247.  
  1248.     VectorAdd(start, forward, start);
  1249.     gi.WriteByte (svc_temp_entity);
  1250.     gi.WriteByte (TE_SMART_MUZZLEFLASH);
  1251.     gi.WritePosition (start);
  1252.     gi.multicast (start, MULTICAST_PVS);
  1253.  
  1254.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  1255.         ent->client->pers.inventory[ent->client->ammo_index]--;
  1256. }
  1257. void weapon_shotgun_fire (edict_t *ent)
  1258. {
  1259.     vec3_t        start;
  1260.     vec3_t        forward, right;
  1261.     vec3_t        offset;
  1262.     int            damage = 4;
  1263.     int            kick = 8;
  1264.  
  1265.     if (ent->client->ps.gunframe == 9)
  1266.     {
  1267.         ent->client->ps.gunframe++;
  1268.         return;
  1269.     }
  1270.  
  1271.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  1272.  
  1273.     VectorScale (forward, -2, ent->client->kick_origin);
  1274.     ent->client->kick_angles[0] = -2;
  1275.  
  1276.     VectorSet(offset, 0, 8,  ent->viewheight-8);
  1277.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  1278.  
  1279.     if (is_quad)
  1280.     {
  1281.         damage *= 4;
  1282.         kick *= 4;
  1283.     }
  1284.  
  1285.     if (deathmatch->value)
  1286.         fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN);
  1287.     else
  1288.         fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN);
  1289.  
  1290.     // send muzzle flash
  1291.     gi.WriteByte (svc_muzzleflash);
  1292.     gi.WriteShort (ent-g_edicts);
  1293.     gi.WriteByte (MZ_SHOTGUN | is_silenced);
  1294.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  1295.  
  1296.     ent->client->ps.gunframe++;
  1297.     PlayerNoise(ent, start, PNOISE_WEAPON);
  1298.  
  1299.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  1300.         ent->client->pers.inventory[ent->client->ammo_index]--;
  1301. }
  1302.  
  1303. void Weapon_Shotgun (edict_t *ent)
  1304. {
  1305.     static int    pause_frames[]    = {22, 28, 34, 0};
  1306.     static int    fire_frames[]    = {7, 0};
  1307.  
  1308.     Weapon_Generic (ent, 3, 11, 31, 35, pause_frames, fire_frames, weapon_floater_fire);
  1309. }
  1310.  
  1311.  
  1312. void weapon_supershotgun_fire (edict_t *ent)
  1313. {
  1314.     vec3_t        start;
  1315.     vec3_t        forward, right;
  1316.     vec3_t        offset;
  1317.     vec3_t        v;
  1318.     int            damage = 6;
  1319.     int            kick = 12;
  1320.  
  1321.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  1322.  
  1323.     VectorScale (forward, -2, ent->client->kick_origin);
  1324.     ent->client->kick_angles[0] = -2;
  1325.  
  1326.     VectorSet(offset, 0, 8,  ent->viewheight-8);
  1327.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  1328.  
  1329.     if (is_quad)
  1330.     {
  1331.         damage *= 4;
  1332.         kick *= 4;
  1333.     }
  1334.  
  1335.     v[PITCH] = ent->client->v_angle[PITCH];
  1336.     v[YAW]   = ent->client->v_angle[YAW] - 5;
  1337.     v[ROLL]  = ent->client->v_angle[ROLL];
  1338.     AngleVectors (v, forward, NULL, NULL);
  1339.     fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
  1340.     v[YAW]   = ent->client->v_angle[YAW] + 5;
  1341.     AngleVectors (v, forward, NULL, NULL);
  1342.     fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
  1343.  
  1344.     // send muzzle flash
  1345.     gi.WriteByte (svc_muzzleflash);
  1346.     gi.WriteShort (ent-g_edicts);
  1347.     gi.WriteByte (MZ_SSHOTGUN | is_silenced);
  1348.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  1349.  
  1350.     ent->client->ps.gunframe++;
  1351.     PlayerNoise(ent, start, PNOISE_WEAPON);
  1352.  
  1353.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  1354.         ent->client->pers.inventory[ent->client->ammo_index] -= 2;
  1355. }
  1356.  
  1357. void Weapon_GrenadeLauncher (edict_t *ent)
  1358. {
  1359.     static int    pause_frames[]    = {25, 33, 42, 50, 0};
  1360.     static int    fire_frames[]    = {5, 9, 0};
  1361.  
  1362.     Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, weapon_sidewinder_fire);
  1363. }
  1364.  
  1365.  
  1366.  
  1367. /*
  1368. ======================================================================
  1369.  
  1370. RAILGUN
  1371.  
  1372. ======================================================================
  1373. */
  1374.  
  1375. void weapon_railgun_fire (edict_t *ent)
  1376. {
  1377.     vec3_t        start;
  1378.     vec3_t        forward, right;
  1379.     vec3_t        offset;
  1380.     int            damage;
  1381.     int            kick;
  1382.  
  1383.     if (deathmatch->value)
  1384.     {    // normal damage is too extreme in dm
  1385.         damage = 100;
  1386.         kick = 200;
  1387.     }
  1388.     else
  1389.     {
  1390.         damage = 250;
  1391.         kick = 250;
  1392.     }
  1393.  
  1394.     if (is_quad)
  1395.     {
  1396.         damage *= 4;
  1397.         kick *= 4;
  1398.     }
  1399.  
  1400.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  1401.  
  1402.     VectorScale (forward, -3, ent->client->kick_origin);
  1403.     ent->client->kick_angles[0] = -3;
  1404.  
  1405.     VectorSet(offset, 32, 5,  ent->viewheight-5);
  1406.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  1407.     fire_rail (ent, start, forward, damage, kick);
  1408.  
  1409.     // send muzzle flash
  1410.     gi.WriteByte (svc_muzzleflash);
  1411.     gi.WriteShort (ent-g_edicts);
  1412.     gi.WriteByte (MZ_RAILGUN | is_silenced);
  1413.     gi.multicast (ent->s.origin, MULTICAST_PVS);
  1414.  
  1415.     ent->client->ps.gunframe++;
  1416.     PlayerNoise(ent, start, PNOISE_WEAPON);
  1417.  
  1418.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  1419.         ent->client->pers.inventory[ent->client->ammo_index]--;
  1420. }
  1421.  
  1422.  
  1423. void Weapon_HyperBlaster (edict_t *ent)
  1424. {
  1425.     static int    pause_frames[]    = {25, 33, 42, 50, 0};
  1426.     static int    fire_frames[]    = {5, 0};
  1427.  
  1428.     Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, weapon_plasma_fire);
  1429. }
  1430.  
  1431.  
  1432. /*
  1433. ======================================================================
  1434.  
  1435. BFG10K
  1436.  
  1437. ======================================================================
  1438. */
  1439.  
  1440. void weapon_bfg_fire (edict_t *ent)
  1441. {
  1442.     vec3_t    offset, start;
  1443.     vec3_t    forward, right;
  1444.     int        damage;
  1445.     float    damage_radius = 1000;
  1446.  
  1447.     if (deathmatch->value)
  1448.         damage = 200;
  1449.     else
  1450.         damage = 500;
  1451.  
  1452.     if (ent->client->ps.gunframe == 9)
  1453.     {
  1454.         // send muzzle flash
  1455.         gi.WriteByte (svc_muzzleflash);
  1456.         gi.WriteShort (ent-g_edicts);
  1457.         gi.WriteByte (MZ_BFG | is_silenced);
  1458.         gi.multicast (ent->s.origin, MULTICAST_PVS);
  1459.  
  1460.         ent->client->ps.gunframe++;
  1461.  
  1462.         PlayerNoise(ent, start, PNOISE_WEAPON);
  1463.         return;
  1464.     }
  1465.  
  1466.     // cells can go down during windup (from power armor hits), so
  1467.     // check again and abort firing if we don't have enough now
  1468.     if (ent->client->pers.inventory[ent->client->ammo_index] < 50)
  1469.     {
  1470.         ent->client->ps.gunframe++;
  1471.         return;
  1472.     }
  1473.  
  1474.     if (is_quad)
  1475.         damage *= 4;
  1476.  
  1477.     AngleVectors (ent->client->v_angle, forward, right, NULL);
  1478.  
  1479.     VectorScale (forward, -2, ent->client->kick_origin);
  1480.  
  1481.     // make a big pitch kick with an inverse fall
  1482.     ent->client->v_dmg_pitch = -40;
  1483.     ent->client->v_dmg_roll = crandom()*8;
  1484.     ent->client->v_dmg_time = level.time + DAMAGE_TIME;
  1485.  
  1486.     VectorSet(offset, 8, 8, ent->viewheight-8);
  1487.     P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
  1488.     fire_bfg (ent, start, forward, damage, 400, damage_radius);
  1489.  
  1490.     ent->client->ps.gunframe++;
  1491.  
  1492.     PlayerNoise(ent, start, PNOISE_WEAPON);
  1493.  
  1494.     if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
  1495.         ent->client->pers.inventory[ent->client->ammo_index] -= 50;
  1496. }
  1497.  
  1498. void Weapon_BFG (edict_t *ent)
  1499. {
  1500.     static int    pause_frames[]    = {39, 45, 50, 55, 0};
  1501.     static int    fire_frames[]    = {9, 0};
  1502.  
  1503.     Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_railgun_fire);
  1504. }
  1505.  
  1506.  
  1507. //======================================================================
  1508.